/*
    Copyright 2011 Peter Pratscher
 
    This file is part of Surveillance.NET.

    Surveillance.NET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    Surveillance.NET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Surveillance.NET. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Diagnostics;
using System.Threading;
using System.Timers;

namespace SurveillanceDotNet.Model
{
    public class SurveillanceSystem : PropertyChangedBase
    {
        private volatile bool _ProcessAlarms;
        private System.Timers.Timer _AlarmTimeOutTimer;
        private System.Timers.Timer _StartupDelayTimer;

        public RemoteEMailControl RemoteEMailControl { get; set; }

        private string _Status;
        public string Status
        {
            get
            {
                return _Status;
            }
            set
            {
                _Status = value;
                OnPropertyChanged("Status");
            }
        }

        private static object _Locker = new object();

        public SurveillanceSystem()
        {
            _ProcessAlarms = false;

            _AlarmTimeOutTimer = new System.Timers.Timer();
            _AlarmTimeOutTimer.Elapsed += new ElapsedEventHandler(_AlarmTimeOutTimer_Elapsed);

            _StartupDelayTimer = new System.Timers.Timer();
            _StartupDelayTimer.Elapsed += new ElapsedEventHandler(_StartupDelayTimer_Elapsed);

            Status = "Stopped";
        }

        void _StartupDelayTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _ProcessAlarms = true;
            _StartupDelayTimer.Stop();

            if (Status != "Stopped")
                Status = "Running (Armed)";
        }

        void _AlarmTimeOutTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Debug.WriteLine(DateTime.Now.ToString() + " - Enabling alarms");

            _AlarmTimeOutTimer.Stop();
            _ProcessAlarms = true;

            Status = "Running (Armed)";
        }

        public void StartSystem(int timeOut)
        {
            _ProcessAlarms = false;
            _AlarmTimeOutTimer.Interval = Database.Instance.AlarmTimeOutPeriod;

            foreach (SurveillanceCamera camera in Database.Instance.Cameras)
            {
                camera.StartMonitoring();
                camera.Alarm += new AlarmEventHandler(camera_Alarm);
            }

            foreach (RegularAction action in Database.Instance.RegularActions)
            {
                action.Start();
            }

            _StartupDelayTimer.Interval = timeOut;
            _StartupDelayTimer.Start();

            if (Database.Instance.EnableRemoteEMailControl)
                Database.Instance.RemoteEMailControl.Start();

            Status = "Running (Disarmed)";
        }

        public void StopSystem()
        {
            _ProcessAlarms = false;

            foreach (SurveillanceCamera camera in Database.Instance.Cameras)
            {
                camera.Alarm -= camera_Alarm;
                camera.StopMonitoring();
            }

            foreach (RegularAction action in Database.Instance.RegularActions)
            {
                action.Stop();
            }

            if (Database.Instance.EnableRemoteEMailControl)
                Database.Instance.RemoteEMailControl.Stop();

            Status = "Stopped";
        }

        void camera_Alarm(object sender, EventArgs e)
        {
            lock (_Locker)
            {
                if (_ProcessAlarms)
                {
                    ScreenUtils.PreventSleep(); //Wake PC if in screensaver mode

                    Status = "Alarm";
                    Debug.WriteLine(DateTime.Now.ToString() + " - Alarm triggered");
                    _ProcessAlarms = false;
                    Debug.WriteLine(DateTime.Now.ToString() + " - Disabling alarms");
                    _AlarmTimeOutTimer.Start();
                    foreach (AlarmAction action in Database.Instance.AlarmActions)
                    {
                        new Thread(new ThreadStart(action.Action)).Start();
                    }

                    ScreenUtils.EnableSleep();
                }
            }
        }
    }
}
